home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
public
/
bit
/
src
/
forms
/
FORMS
/
input.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
11KB
|
395 lines
/*
* input.c
*
* Forms Object class: INPUT
*
* Written by: Mark Overmars and Anthony Woodward
*
* Version 2.1 b
* Date: Sep 29, 1992
*/
#include <malloc.h>
#include <stdio.h>
#include <strings.h>
#include <stdlib.h>
#include <sys/types.h>
#include "gl/device.h"
#include "forms.h"
/* Extra information need for input boxes. */
typedef struct {
int textcol; /* text color */
int curscol; /* cursor color */
int position; /* cursor position */
int beginrange; /* start of the range */
int endrange; /* end of the range */
char *str; /* the input text */
int size; /* size of the string */
int changed; /* whether the field has changed */
int always; /* whether to return value always */
} SPEC;
static void draw_input(FL_OBJECT *ob)
{
int col,textcol,valign;
float xmargin, ymargin;
SPEC *sp = ((SPEC *)(ob->spec));
if (ob->focus) col = ob->col2; else col = ob->col1;
fl_drw_box(ob->boxtype,ob->x,ob->y,ob->w,ob->h,col,FL_INPUT_BW);
fl_drw_text_beside(ob->align,ob->x,ob->y,ob->w,ob->h,
ob->lcol,ob->lsize,ob->lstyle,ob->label);
if (ob->type == FL_MULTILINE_INPUT) valign = 1; else valign = 0;
if (ob->boxtype == FL_UP_BOX || ob->boxtype == FL_DOWN_BOX ||
ob->boxtype == FL_ROUNDED_BOX || ob->boxtype == FL_RSHADOW_BOX ||
ob->boxtype == FL_RFLAT_BOX)
{ xmargin = 2.0*FL_INPUT_BW; ymargin = 1.5*FL_INPUT_BW;}
else
{ xmargin = 1.0*FL_INPUT_BW; ymargin = 0.5*FL_INPUT_BW;}
if (ob->type == FL_SECRET_INPUT) textcol = col; else textcol = sp->textcol;
fl_drw_string(-1,valign, /* Align left centered. */
ob->x+xmargin, /* Bounding box */
ob->y+ymargin,
ob->w-2.0*xmargin,
ob->h-2.0*ymargin,
TRUE, /* Do clipping */
col,textcol,sp->curscol, /* Colors */
ob->lsize,ob->lstyle, /* Size and style */
sp->position, /* Cursor position */
sp->beginrange,sp->endrange, /* Selection range */
sp->str);
}
static int handle_select(float mx, float my, FL_OBJECT *ob, int mouse)
/* figures out selection region of mouse. Returns whether anything changed */
{
SPEC *sp = ((SPEC *)(ob->spec));
int thepos;
int oldpos = sp->position;
int oldbeg = sp->beginrange;
int oldend = sp->endrange;
int valign;
float xmargin,ymargin;
if (ob->type == FL_HIDDEN_INPUT || ob->type == FL_SECRET_INPUT) return 0;
/* Compute the mouse position in the string */
if (ob->type == FL_MULTILINE_INPUT) valign = 1; else valign = 0;
if (ob->boxtype == FL_UP_BOX || ob->boxtype == FL_DOWN_BOX ||
ob->boxtype == FL_ROUNDED_BOX || ob->boxtype == FL_RSHADOW_BOX ||
ob->boxtype == FL_RFLAT_BOX)
{ xmargin = 2.0*FL_INPUT_BW; ymargin = 1.5*FL_INPUT_BW;}
else
{ xmargin = 1.0*FL_INPUT_BW; ymargin = 0.5*FL_INPUT_BW;}
thepos = fl_get_pos_in_string(-1,valign,
ob->x+xmargin,
ob->y+ymargin,
ob->w-2.0*xmargin,
ob->h-2.0*ymargin,
ob->lsize, ob->lstyle,
mx,my,sp->str);
/* Adapt the range */
if (mouse)
{
if (thepos < sp->position)
{ sp->endrange = sp->position; sp->beginrange = thepos;}
else
{ sp->beginrange = sp->position; sp->endrange = thepos;}
}
else
{ sp->position = sp->beginrange = thepos; sp->endrange = -1; }
if (sp->beginrange == sp->endrange) sp->endrange = -1;
return (oldpos != sp->position || oldbeg != sp->beginrange ||
oldend != sp->endrange);
}
static void delete_piece(FL_OBJECT *ob, int beginrange, int endrange)
/* Removes a piece of the string */
{
SPEC *sp = ((SPEC *)(ob->spec));
int i = 0;
do {
i++;
sp->str[beginrange+i-1] = sp->str[endrange+i];
} while (sp->str[endrange+i] != '\0');
sp->position = beginrange;
}
static float get_substring_width(FL_OBJECT *ob, int startpos, int endpos)
/* Returns the width of the substring of the input field */
{
SPEC *sp = ((SPEC *)(ob->spec));
char tmpch = sp->str[endpos]; /* Save end position */
float wid; /* The required width */
sp->str[endpos] = '\0';
wid = fl_get_string_width(ob->lsize,ob->lstyle,&(sp->str[startpos]));
sp->str[endpos] = tmpch; /* Restore end position */
return wid;
}
static int handle_key(FL_OBJECT *ob, char key)
/* Handles a key press, returns whether something has changed */
{
int i, ret = 1;
SPEC *sp = ((SPEC *)(ob->spec));
char *ptr; /* pointer to string */
char *old; /* store previous value */
int oldpos; /* old position */
int slen; /* length of the string */
int startpos; /* position of start of current line */
float wid,oldwid,tt; /* width of substring */
int ready;
/* Save old situation */
if (ob->type == FL_FLOAT_INPUT || ob->type == FL_INT_INPUT)
{
oldpos = sp->position;
old = (char *) fl_malloc(sp->size+1);
strcpy(old,sp->str);
}
/* Extend field size if required */
slen = strlen(sp->str);
if (sp->size == slen+1)
{
sp->size += 8;
sp->str = (char *) realloc(sp->str,sp->size);
}
if (ob->type == FL_MULTILINE_INPUT && key == 13) key = 10;
/* Compute starting position of current line */
startpos = sp->position;
while (startpos > 0 && sp->str[startpos-1] != 10) startpos--;
switch (key)
{
case 1: /* Left key */
if (getbutton(LEFTSHIFTKEY) || getbutton(RIGHTSHIFTKEY))
while (sp->position > 0 && sp->str[sp->position-1] != 10)
sp->position--;
else if (sp->position >0)
sp->position--;
ret = 0;
break;
case 2: /* Right key */
if (getbutton(LEFTSHIFTKEY) || getbutton(RIGHTSHIFTKEY))
while (sp->position < slen && sp->str[sp->position] != 10)
sp->position++;
else if (sp->position < slen)
sp->position++;
ret = 0;
break;
case 3: /* Up key */
if (getbutton(LEFTSHIFTKEY) || getbutton(RIGHTSHIFTKEY))
sp->position = 0;
else if (startpos != 0)
{
wid = get_substring_width(ob,startpos,sp->position);
i = startpos -1;
while (i > 0 && sp->str[i-1] != 10) i--;
oldwid = 0.0;
sp->position = i;
ready = (sp->str[sp->position] == 10);
while (!ready)
{
tt = get_substring_width(ob,i,sp->position+1);
ready = (oldwid+tt)/2.0 >= wid;
oldwid = tt;
if (!ready) sp->position++;
if (sp->str[sp->position] == 10) ready = TRUE;
}
}
ret = 0;
break;
case 4: /* Down key */
if (getbutton(LEFTSHIFTKEY) || getbutton(RIGHTSHIFTKEY))
sp->position = slen;
else
{
wid = get_substring_width(ob,startpos,sp->position);
i = sp->position+1;
while (i < slen && sp->str[i-1] != 10) i++;
if (i < slen)
{
oldwid = 0.0;
sp->position = i;
ready = (sp->position == slen || sp->str[sp->position] == 10);
while (!ready)
{
tt = get_substring_width(ob,i,sp->position+1);
ready = (oldwid+tt)/2.0 >= wid;
oldwid = tt;
if (!ready) sp->position++;
if (sp->position == slen || sp->str[sp->position] == 10)
ready = TRUE;
}
}
}
ret = 0;
break;
case 0x7f: /* Delete key*/
if (sp->endrange >= 0)
delete_piece(ob,sp->beginrange,sp->endrange-1);
else if (sp->position < slen)
delete_piece(ob,sp->position,sp->position);
else
ret = 0;
break;
case 8: /* Backspace */
if (sp->endrange >= 0)
delete_piece(ob,sp->beginrange,sp->endrange-1);
else if (sp->position >0)
delete_piece(ob,sp->position-1,sp->position-1);
else
ret = 0;
break;
case 27: /* Esc key */
if (slen>0)
delete_piece(ob,0,slen-1);
else
ret = 0;
break;
default:
if ( key >= 32 || key == 10) /* Normal keys or NL*/
{
if (sp->endrange >= 0)
delete_piece(ob,sp->beginrange,sp->endrange-1);
/* Add the character */
for (i=slen+1; i>sp->position; i--)
sp->str[i] = sp->str[i-1];
sp->str[sp->position] = key;
sp->position++;
}
else
return 0;
}
sp->endrange = -1;
/* Check whether change was correct. */
if (ob->type == FL_FLOAT_INPUT || ob->type == FL_INT_INPUT)
{
if (ob->type == FL_FLOAT_INPUT)
strtod(sp->str,&ptr);
else
strtol(sp->str,&ptr,10);
slen = strlen(sp->str);
if (*ptr != '\0' && strcmp(sp->str,"-") != 0 &&
(sp->str[slen-1] != '-' || sp->str[slen-2] != 'e'))
{ strcpy(sp->str,old); sp->position = oldpos; ringbell(); ret = 0;}
free(old);
}
fl_redraw_object(ob);
return ret;
}
static int handle_input(FL_OBJECT *ob,int event,float mx,float my,char key)
/* Handles an event */
{
SPEC *sp = ((SPEC *)(ob->spec));
switch (event)
{
case FL_DRAW:
if (ob->type != FL_HIDDEN_INPUT) draw_input(ob);
return 0;
case FL_FOCUS:
sp->position = strlen(sp->str);
sp->changed = FALSE;
fl_redraw_object(ob);
return 0;
case FL_UNFOCUS:
sp->position = -1;
sp->endrange = -1;
fl_redraw_object(ob);
return sp->changed;
case FL_MOUSE:
if (handle_select(mx,my,ob,TRUE)) fl_redraw_object(ob);
return 0;
case FL_PUSH:
if (handle_select(mx,my,ob,FALSE)) fl_redraw_object(ob);
return 0;
case FL_KEYBOARD:
if (handle_key(ob,key))
{
sp->changed = TRUE;
return (sp->always);
}
else
return 0;
case FL_FREEMEM:
free(((SPEC *)(ob->spec))->str);
free(ob->spec);
return 0;
}
return 0;
}
/*------------------------------*/
FL_OBJECT *fl_create_input(int type,float x,float y,float w,float h,const
char *label)
/* creates an object */
{
FL_OBJECT *ob;
ob = fl_make_object(FL_INPUT,type,x,y,w,h,label,handle_input);
ob->boxtype = FL_INPUT_BOXTYPE;
ob->col1 = FL_INPUT_COL1;
ob->col2 = FL_INPUT_COL2;
ob->align = FL_INPUT_ALIGN;
ob->lcol = FL_INPUT_LCOL;
ob->input = 1;
ob->wantall = (ob->type == FL_MULTILINE_INPUT);
ob->spec = (int *) fl_malloc(sizeof(SPEC));
((SPEC *)(ob->spec))->textcol = FL_INPUT_TCOL;
((SPEC *)(ob->spec))->curscol = FL_INPUT_CCOL;
((SPEC *)(ob->spec))->position = -1;
((SPEC *)(ob->spec))->endrange = -1;
((SPEC *)(ob->spec))->size = 8;
((SPEC *)(ob->spec))->str = (char *) fl_malloc(8);
((SPEC *)(ob->spec))->str[0] = '\0';
((SPEC *)(ob->spec))->always = 0;
return ob;
}
FL_OBJECT *fl_add_input(int type, float x, float y, float w, float h, const
char *label)
/* Adds an object */
{
FL_OBJECT *ob;
ob = fl_create_input(type,x,y,w,h,label);
fl_add_object(fl_current_form,ob);
return ob;
}
void fl_set_input(FL_OBJECT *ob, const char *str)
/* Sets the particular input string. */
{
SPEC *sp = ((SPEC *)(ob->spec));
if (sp->size < strlen(str)+1)
{
sp->size = strlen(str)+1;
sp->str = (char *) realloc(sp->str,sp->size);
}
strcpy(sp->str,str);
if (sp->position != -1) sp->position = strlen(sp->str);
sp->endrange = -1;
fl_redraw_object(ob);
}
void fl_set_input_color(FL_OBJECT *ob, int textcol, int curscol)
/* Sets the color of the input string. */
{
((SPEC *)(ob->spec))->textcol = textcol;
((SPEC *)(ob->spec))->curscol = curscol;
fl_redraw_object(ob);
}
const char *fl_get_input(FL_OBJECT *ob)
/* returns a pointer to the text string */
{ return ((SPEC *)(ob->spec))->str; }
void fl_set_input_return(FL_OBJECT *ob, int value)
/* Sets whether to return value all the time or only when pressing return */
{
((SPEC *)(ob->spec))->always = value;
}